home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 17
/
CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso
/
CUCD
/
Programming
/
DiceSource
/
src
/
dicehelp
/
DICEHelp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-09
|
26KB
|
1,016 lines
/*
* (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
* use is allowed under the terms of the DICE-LICENSE FILE,
* DICE-LICENSE.TXT.
*/
/*
** $Id: DICEHelp.c,v 30.0 1994/06/10 18:05:48 dice Exp $
**
** Dice help system. Searches an index file for a given
** keyword. Returns either filename information, or the actual
** clip to the console, clipboard, or Rexx RESULT.
**
*/
/*
**
** BUGS
** REXXSTARTUP should exit if already resident. (No, kill old).
**
** Looses $30 (48) bytes of memory when started from Workbench.
**
** CLI/WB invocation should use resident index file
**
** If memory is less than XX bytes free, flush self on exit.
**
** DICEHelp from Workbench accounts for "reasonable" font
** sizes. Very large font sizes, however, blow it up.
**
** !!!TODO
** If cursor is on "console.doc" in
** "work:doc/doc/console.doc/OpenDevice",
** return the console doc in full.
**
** (Return # of lines for editor to open window?
** Useful for small clips).
**
** Make search faster -- check case insensitive first.
** (Actually this is obsolete -- new tokenized index file
** is needed to deal with automatic multiple references).
**
** Match plural mismatch with error index of -3? (See error
** weighting system).
**
** Workbench won't read full files directly.
**
** New HELP Items:
** Put Carolyn's 68000 cards on line. She says this is OK,
** with credit.
**
** Help on error messages.
**
** Help on C keywords
**
*/
#define D(x) ;
#define X(x) ;
#undef CLIPSUPPORT /* Enable/disable clipboard.device code.
Clipboard support is slightly broken right now, but could be fixed */
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <rexx/rxslib.h>
#include <clib/rexxsyslib_protos.h>
#include <dos/dos.h>
#include <exec/memory.h>
#ifdef CLIPSUPPORT
#include <devices/clipboard.h>
#endif
#include <DICEHelp_rev.h>
#include <strings.h>
#include <stdio.h>
#include <ctype.h>
/*******************************************************************************
** Errors.
*/
#define OK_TEMPFILE 1 // Tempfile has been created
#define OK_FULLFILE 2 // Full path name has been returned
#define ERROR_NOTOOLTYPE 3 // No VIEWER tooltype
#define ERROR_NOTFOUND 4 // Can't find search string
#define ERROR_BADFORMAT 5 // Badly formatted line in index file
#define ERROR_BADCOMMAND 6 // Unrecognised AREXX command
#define ERROR_READFILE 7 // Error reading help file
#define ERROR_NOMEMORY 8 // Out of memory error
#define ERROR_WRITEFILE 9 // Error writing temporary file to T: !!!
#define ERROR_NOCLIP 10 // Can't open clipboard.device !!!
#define ERROR_NOCLIPSUP 11 // Don't even support clipboard
#define ERROR_INTERNAL 12 // Ohh, baby!
#define ERROR_MAXERRNO 12 // Distinguish error from pointer
struct ExtRexxMsgPort {
struct MsgPort rmp_Port;
struct MinList rmp_SearchNodes;
};
struct SearchNode {
struct MinNode sn_Node; // Linkage
char * sn_FileName; // Full path to load file from
char * sn_FileData; // Loaded file, or NULL if unloaded
unsigned long sn_FileSize; // Length of file, if known
};
#define unless(x) if(!(x))
#define until(x) while(!(x))
/*******************************************************************************
** Prototypes
*/
void *rexxOpen(void);
void rexxClose(void);
void rexxReply(struct RexxMsg *msg,int Result1,int Result2,char *string);
void *clipOpen(void);
void clipClose(void);
LONG clipWrite(char *string);
LONG clipLongWrite(LONG *ldata);
char *getHelp(int outmode, char *searchline, int curpos);
char *searchOpen(void);
void searchClose(void);
char *searchMe(char *strings,char *searchfor,char **filename);
void convertFile(char *file,ULONG length);
void debugPrintSN(void);
void startOutput( char outmode );
void sendOutput( char outmode, char *outstring, ULONG outlength );
char *endOutput( char outmode );
char *StringScan( char *instring );
char *tailpath_p( char *searchline );
int isCollectable(char c);
char *ErrorText( int error, void * auxdata );
/*******************************************************************************
** Globals
*/
struct RsxLib *RexxSysBase =0; // Rexxsyslib.library base
struct MsgPort *rexxPort =0; // Our Rexx port
struct IOClipReq *clipIO =0; // Clipboard Access
struct List SearchNodes; // List of struct SearchNode
char rexxName[]="DICEHELP"; // !! No string optimization
#define PORT_PRI 5 // Slighly above the rabble
const char IdString[] = { VERSTAG };
#define OUTMODE_CLIP 'C'
#define OUTMODE_STDOUT 'S'
#define OUTMODE_FILE 'T'
#define OUTMODE_CRUTCHES 'Z'
#define COMMAND_QUIT 'Q'
#define TEMPFILE_NAME "t:DICEHelp.temp" // hard coded, too
#define TEMPFILE_LEN 15 // DICE has no strlen() optimization
disable_break()
{
return(0);
}
/*******************************************************************************
**
** Workbench support
*/
#include "intuition/intuition.h"
#include <clib/intuition_protos.h>
#include <clib/icon_protos.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#define STRING_MAX 90 // !! Fixed size
char buf_string[STRING_MAX]; // !! Fixed size
char inp_string[STRING_MAX]; // !! Fixed size
char commandline[STRING_MAX]; // !! Fixed size
#define GX 10
#define GY 25
#define GWIDTH 400
#define GHEIGHT 30
struct StringInfo si =
{
inp_string, // String
NULL, // Undo
0, // Buffer position
STRING_MAX, // Count
0, // Disp Pos
0, // Undo pos
0, // Num Chars
0, // DispCount
0,0, // CLeft,CTop
NULL, // Layer
0, // LongInt
NULL // Alternate keymap
};
struct Gadget gt =
{
NULL,
GX,GY,
GWIDTH,GHEIGHT,
GADGHBOX,
RELVERIFY,
STRGADGET,
NULL,
NULL,
NULL,
0,
&si,
0,
NULL
};
struct NewWindow nw =
{
((640-GWIDTH+20)/2),75, /* Left, Top */
GWIDTH+20,GHEIGHT+20,
-1,-1,
IDCMP_CLOSEWINDOW|IDCMP_GADGETUP,
WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|
WFLG_SMART_REFRESH|WFLG_ACTIVATE,
>,
NULL,
"DICEHelp: Please enter a word:",
NULL,NULL,
0,0,
0,0,
WBENCHSCREEN
};
int wbmain(struct WBStartup *wbs)
{
struct Window * win;
struct IntuiMessage * msg=0;
char * filename=0;
char * temp=0;
int rc=0;
if ( win=OpenWindow(&nw) ) {
SetAPen(win->RPort,2);
if ((win->Height-win->BorderBottom-1) > 0) {
RectFill(win->RPort,
win->BorderLeft,
win->BorderTop,
win->Width-win->BorderRight-1,
win->Height-win->BorderBottom-1,
);
}
ActivateGadget(>,win,NULL);
// Collect VIEWER tooltype into commandline array, else
// set RC=ERROR_NOTOOLTYPE
{
struct DiskObject * dob; // DICEHelp icon (for Tooltypes)
BPTR saveLock;
saveLock = CurrentDir((BPTR)wbs->sm_ArgList[0].wa_Lock);
if (dob = GetDiskObject(wbs->sm_ArgList[0].wa_Name)) {
if (temp=FindToolType(dob->do_ToolTypes,"VIEWER") ) {
strncpy(commandline,temp,STRING_MAX-TEMPFILE_LEN-2);
strncat(commandline," ",STRING_MAX);
strncat(commandline,TEMPFILE_NAME,STRING_MAX);
} else {
SetWindowTitles(win,"No \"VIEWER\" ToolType in icon!",(void *)-1);
rc= ERROR_NOTOOLTYPE;
// Window stays open for message, but user can't do anything.
}
FreeDiskObject(dob);
}
CurrentDir(saveLock);
}
unless( searchOpen() ) {
SetWindowTitles(win,"Can't open file \"s:DICEHelp.index\"!",(void *)-1);
rc= ERROR_READFILE;
// Window stays open for message, but user can't do anything.
}
// Loop until we process a message (Any message causes us to exit
int looping=1;
while(looping && Wait(1L << win->UserPort->mp_SigBit))
{
while(msg = (struct IntuiMessage *) GetMsg(win->UserPort) )
{
switch( msg->Class )
{
case CLOSEWINDOW:
looping=0;
break;
case GADGETUP:
if (!rc) {
char *msg;
SetWindowTitles(win, commandline,(void *)-1);
msg = getHelp( OUTMODE_FILE, inp_string, 0 );
if (msg == NULL)
msg = "E Internal error!";
if (msg[0] != 'T') {
DisplayBeep(0L);
SetWindowTitles(win, msg+2, (void *)-1);
looping=1; // Stay, show message
ActivateGadget(>,win,NULL); // Re-juice gadget
} else {
//
// !!!! :TODO:
// Under 2.0: fh=Open("CON:0/0/200/200/DICEHelp Error/AUTO/CLOSE/WAIT",MODE_NEWFILE);
// Under 1.3: fh=Open("NIL:",MODE_NEWFILE);
//
// Note: Execute does not return a sane code under 2.0!
//
if( Execute(commandline,NULL,Open("NIL:",MODE_NEWFILE)) )
looping=0;
else
DisplayBeep(0L);
}
}
break;
default:
}
ReplyMsg( (struct Message *)msg );
}
}
if (win) CloseWindow(win);
searchClose();
} // OpenWindow
}
/*******************************************************************************
** CLI Startup
*/
main(int argc,char * argv[])
{
struct RexxMsg *msg;
char *filename=0;
char *refline =0;
char *temp=0;
char outmode=0;
char *rexxresult=0;
int returncode=0;
onbreak( disable_break );
if (argc != 2 || ( argc == 2 && *argv[1]=='?' ) ) {
printf("DICEhelp <Searchstring> [REXXSTARTUP]\n");
printf("; Return help for searchstring. See MakeIndex & s:DICEHelp.index\n");
exit(5);
}
unless( searchOpen() ) {
puts( ErrorText( ERROR_READFILE, "s:DICEHelp.index" ));
exit(10); // !!! Modify to return REXX result
}
if( strcmp(argv[1],"REXXSTARTUP") )
{
temp=getHelp( OUTMODE_STDOUT, argv[1], 0 );
unless( temp[0] == 'S')
puts( temp+2 ); // Error
}
else{ // REXXSTARTUP
unless( rexxOpen() ) { // !!! Error check
printf("Error: Can't open \"rexxsyslib.library\"\n");
}
#ifdef CLIPSUPPORT
unless( clipOpen() ) {
printf("Error: Can't open \"clipboard.device\"\n");
}
#endif
D(printf("REXX port open for traffic!\n"));
until( outmode == 'Q' || SIGBREAKF_CTRL_C &
Wait(1L << rexxPort->mp_SigBit | SIGBREAKF_CTRL_C) ) {
while( msg=(struct RexxMsg *)GetMsg((struct MsgPort *)rexxPort) ) {
temp = msg->rm_Args[0];
D(printf("Message %lx, rm_Args[0] @ %lx:\n%s\n",msg,temp,temp));
rexxresult=0;
returncode = ERROR_BADCOMMAND;
if( (3 < strlen(temp)) && (temp[1]==' ') )
{
outmode = temp[0];
printf("Outmode = %c\n", outmode);
if ( outmode == 'Q' )
rexxresult = "QUITTING";
else if ( outmode == 'Z' )
rexxresult = getHelp( OUTMODE_FILE, &temp[2], -1 );
else
rexxresult = getHelp( OUTMODE_FILE, &temp[2], 0 );
}
if( rexxresult )
returncode = 0;
rexxReply( msg,returncode,0,rexxresult );
} // While messages
} // Until exit
#ifdef CLIPSUPPORT
clipClose();
#endif
rexxClose();
}
D(printf("Exiting...\n"));
searchClose();
return(returncode);
}
#ifdef NOTDEF
/*******************************************************************************
** Debug functions
*/
void debugPrintSN(void)
{
struct SearchNode *nd=(struct SearchNode *)&SearchNodes;
while((nd=nd->sn_Node.mln_Succ) && (nd->sn_Node.mln_Succ)) {
printf("SearchNode at %lx\n",nd);
printf("sn_FileName =%s\n",nd->sn_FileName);
printf("sn_FileSize =%ld\n",nd->sn_FileSize);
printf("sn_FileData =%lx\n\n",nd->sn_FileData);
}
}
#endif
/*******************************************************************************
** Index file functions
*/
#define FILE_PAD 2 // Stick two NULLs at the end of the file
char *searchOpen(void)
{
struct SearchNode *sn;
ULONG fh=0;
ULONG length;
char *body=0;
char *filename="s:DICEHelp.index";
NewList(&SearchNodes);
if (fh=Open(filename,MODE_OLDFILE)) {
Seek(fh,0,OFFSET_END);
if (length=Seek(fh,0,OFFSET_BEGINNING)) {
if (sn=AllocMem(sizeof(struct SearchNode),0)) {
sn->sn_FileName=filename;
sn->sn_FileData=0;
sn->sn_FileSize=length+FILE_PAD;
AddTail(&SearchNodes,(struct Node *)sn);
if (body=AllocMem(length+FILE_PAD,0)) {
if (length==Read(fh,body,length)) {
sn->sn_FileData=body;
convertFile(body,length); // LF->NULL & Terminate
} else {
FreeMem(body,sn->sn_FileSize);
}
}
}
}
}
if(fh)
Close(fh);
return(body);
}
void searchClose(void)
{
struct SearchNode *sn;
struct SearchNode *nn;
nn=(struct SearchNode *)&SearchNodes;
nn=(struct SearchNode *)nn->sn_Node.mln_Succ;
while( nn && nn->sn_Node.mln_Succ) {
sn=nn;
nn=(struct SearchNode *)nn->sn_Node.mln_Succ;
D(printf("Freeing searchnode %s. %d bytes\n",sn->sn_FileName,
sn->sn_FileSize));
if( sn->sn_FileData )
FreeMem(sn->sn_FileData,sn->sn_FileSize);
FreeMem(sn,sizeof(struct SearchNode));
}
}
/*******************************************************************************
** Line parsing functions
**
** Some editors have lousy "get word" functions. Given a cursor
** position and a line, we can clip out words too.
**
** ?? If the cursor is ON punctuation, return it ??
**
** The result is NULL or a pointer into the string. The end of
** the parsed word is NULL terminated, ** MODIFYING ** the input.
**
** Input lines are formatted with XX equal to the cursor position:
** Z XX Clipped line
** String is at least 4 characters long.
**
*/
int isCollectable(char c)
{
if( isalnum(c) || c==':' || c=='/' || c=='_' || c=='.' || c=='\\' )
return( 1 );
return( 0 );
}
char * StringScan( char *instring )
{
char *tail;
char *result;
unsigned long curpos;
unsigned long curtemp; // Wordy()
curpos = strtol( instring, &tail, 10 );
D(printf("|Input pos=%ld, Line=%s\n", curpos, tail));
if ( !curpos || (*tail != ' ') ) // !!! longer than string?
return( NULL );
curtemp = curpos;
while( curtemp && isCollectable( tail[curtemp-1] ) )
curtemp--;
result = &tail[curtemp];
D(printf("|Start pos=%ld, Tail=%s\n", curpos, result));
curtemp = curpos;
while( isCollectable( tail[curtemp] ) )
curtemp++; // Stops at trailing NULL, at worst
tail[curtemp]=0;
D(printf("|Final pos=%ld, Result=\"%s\"\n", curtemp, result) );
if( curtemp == curpos ) // If no characters were valid
result = 0;
return( result );
}
/*******************************************************************************
** Output functions. Start, send and end output based on outmode.
*/
ULONG outfh; // For xxxOut functions
void startOutput(char outmode)
{
switch(outmode) {
case OUTMODE_CLIP: // !!! IFF FTXT Length
outfh=1;
break;
case OUTMODE_STDOUT:
outfh=1; // Continuation flag, basically
break;
case OUTMODE_FILE:
case OUTMODE_CRUTCHES:
outfh=Open( TEMPFILE_NAME, MODE_NEWFILE );
break;
default:
}
}
void sendOutput(char outmode, char *outstring,ULONG outlength)
{
char *returnstring=0;
switch(outmode) {
case OUTMODE_CLIP:
#ifdef CLIPSUPPORT
clipWrite(outstring);
#endif
break;
case OUTMODE_STDOUT:
while( outfh && outlength && (outlength=nextLine(outstring)) ) {
if( outlength != fwrite(outstring,1,outlength,stdout) )
outlength=0; // Terminate early
if( SIGBREAKF_CTRL_C & SetSignal( 0,SIGBREAKF_CTRL_C) ) {
outfh = 0;
outlength=0;
}
outstring += outlength;
}
break;
case OUTMODE_FILE:
case OUTMODE_CRUTCHES:
if( outfh )
if( outlength != Write( outfh,outstring,outlength )) {
Close( outfh ); // Prevent multiple "failed"
outfh = NULL; // requesters in case of error
}
break;
default:
}
}
// !! This strings should be moved to ErrorText for localization
char *endOutput( char outmode )
{
char *returnstring="E Internal error!";
switch(outmode) {
case OUTMODE_CLIP:
returnstring="E Clipboard not supported";
break;
case OUTMODE_STDOUT:
returnstring="S stdout";
break;
case OUTMODE_FILE:
case OUTMODE_CRUTCHES:
if( outfh )
Close( outfh );
outfh = NULL;
returnstring="T t:DICEHelp.temp";
break;
default:
}
return( returnstring );
}
/*******************************************************************************
** Arexx functions
*/
void * rexxOpen(void)
{
RexxSysBase = (struct RxsLib *)OpenLibrary("rexxsyslib.library",0L);
if (rexxPort == NULL) {
Forbid();
if (!( rexxPort = FindPort(rexxName ) ))
rexxPort = CreatePort(rexxName, PORT_PRI);
Permit();
}
return( RexxSysBase );
}
void rexxClose(void)
{
if (RexxSysBase) {
CloseLibrary(RexxSysBase);
RexxSysBase=NULL;
}
if (rexxPort)
DeletePort(rexxPort);
}
void rexxReply(struct RexxMsg *msg,int Result1,int Result2,char *string)
{
msg->rm_Result1 = Result1;
msg->rm_Result2 = Result2;
if (Result1 == 0 && (msg->rm_Action & (1L << RXFB_RESULT))) {
D(printf("Rexx Result1=%lx Result2=%s\n",0,string));
if (string && RexxSysBase)
msg->rm_Result2 =
(LONG)CreateArgstring(string, (LONG)strlen(string)) ;
else
msg->rm_Result2 = NULL;
}
D(printf("Rexx Result1=%lx Result2 =%lx\n",msg->rm_Result1,msg->rm_Result2));
ReplyMsg((struct Message *)msg);
}
#ifdef CLIPSUPPORT
/******************************************************************************
** Clipboard functions
*/
void * clipOpen()
{
struct MsgPort *port;
if (port = CreatePort(0L, 0L))
{
if (clipIO = (struct IOClipReq *)
CreateExtIO (port, sizeof (struct IOClipReq)) )
{
unless( OpenDevice ("clipboard.device", 0, clipIO, 0) )
return(clipIO);
DeleteExtIO(clipIO);
clipIO = NULL;
}
DeletePort(port);
}
return(0);
}
void clipClose()
{
if( clipIO ) {
CloseDevice(clipIO);
DeletePort(clipIO->io_Message.mn_ReplyPort);
DeleteExtIO(clipIO);
}
}
LONG clipWrite(char * string)
{
LONG length, slen = strlen (string);
BOOL odd = (slen & 1); /* pad byte flag */
LONG error = 0L;
/* Reset the clip id */
clipIO->io_ClipID = 0;
length = (odd) ? slen + 1 : slen;
clipIO->io_Offset = 0;
error = clipLongWrite ((LONG *) "FORM");/* "FORM" */
length += 12;
error = clipLongWrite (&length); /* # */
error = clipLongWrite ((LONG *) "FTXT");/* "FTXT" for example */
error = clipLongWrite ((LONG *) "CHRS");/* "CHRS" for example */
error = clipLongWrite (&slen); /* # (length of string) */
clipIO->io_Command = CMD_WRITE;
clipIO->io_Error = 0;
clipIO->io_Data = (char *) string;
clipIO->io_Length = slen; /* length of string */
error = (LONG) DoIO (clipIO); /* text string */
/* Write the pad byte */
if (odd)
{
clipIO->io_Command = CMD_WRITE;
clipIO->io_Error = 0;
clipIO->io_Data = NULL;
clipIO->io_Length = 1;
error = (LONG) DoIO (clipIO);
}
/* Indicate that we're done writing to the clipboard */
clipIO->io_Command = CMD_UPDATE;
clipIO->io_Error = 0;
error = (LONG) DoIO (clipIO);
return (error);
}
LONG clipLongWrite (LONG * ldata)
{
clipIO->io_Command = CMD_WRITE;
clipIO->io_Error = 0;
clipIO->io_Data = (char *) ldata;
clipIO->io_Length = 4L;
return ( (LONG) DoIO (clipIO) );
}
#endif
/*******************************************************************************
** Clip & Snip functions
*/
/*
** searchline - Search word, or raw line from editor.
** curpos - Cursor position on line, or zero for no parsing.
** outmode - Where to stuff it.
**
** returns:
** Filename clip is stored in, or name of entire file
** Multiple references
** Name of word searched for
**
** errors:
** Clip not found
** Can't open file
** Bad format
*/
char *getHelp(int outmode, char *searchline, int curpos)
{
struct SearchNode *sn=(struct SearchNode *)&SearchNodes; // Search
int rc=ERROR_NOTFOUND; // Error code
// searchline // Passed: parameter, raw unprocessed line
char * searchword; // Parsed: Word to search for, ie "OpenDevice"
char *refline; // Searched: [searchname] [offset] [lines]
char *filename=0; // Searched: Path name for refline
unsigned long fh=0;
unsigned long startpos; // Calculated from refline
unsigned long length; // Calculated from refline
char * temp=0; // Have bits, will travel.
char * refline2; // Multi-reference buffer
char * filename2; // Multi-reference buffer
char * returnstring=0; // Indicates where to look for result.
// "CLIP"
// "STDOUT"
// "full:path"
// "t:DICEHelp.temp"
/*
** Parse it. Use Z mode if a cursor position is given.
*/
if( curpos ) {
searchline = StringScan( searchline ); // Null terminates searchline-
} // returns interesting part
if( searchline == NULL || strlen( searchline ) < 2 )
return( ErrorText( ERROR_NOTFOUND, "" ));
/*
** Clip off "device:filename/word" to just "word"
*/
searchword = tailpath_p( searchline );
D(printf("\nWord=<%s> Line=<%s>\n",searchword, searchline ));
if( !*searchword ) // Help item contained a trailing :
return( ErrorText( ERROR_NOTFOUND, searchline ));
/*
** Search all lists of words. Reject refline's that don't match
** the expected file name.
*/
refline = 0;
while( !refline && (sn=(struct SearchNode *)sn->sn_Node.mln_Succ) &&
(sn->sn_Node.mln_Succ)) {
if( sn->sn_FileData ) {
temp = sn->sn_FileData;
while( temp = searchMe(temp, searchword, &filename) ) {
D(printf("Search-Filename=%s res=%s cmp=%d\n",
filename, temp, strpathcmp( filename, searchline )));
if( !strpathcmp( filename, searchline ) ) {
refline = temp;
break;
}
temp += strlen( temp )+1;
}
}
}
/*
** Basic parsing of refernce line. Checks for bad format, gets length
** and offset.
*/
unless( refline )
return( ErrorText( ERROR_NOTFOUND, searchword ));
unless( temp=strchr(refline,0x09) ) // Search for tab
return( ErrorText( ERROR_BADFORMAT, 0 ));
startpos=strtol(temp,&temp,16);
length=strtol(temp,&temp,16);
D(printf("Reading %s, startpos %lx, length %lx\nrefline=%s searchword=%s\n",
filename,startpos,length,refline,searchword));
/*
** If the index file specifies the *entire* file, and the mode is
** tempfile, just return the full path name of the file. This saves
** reading the file twice, as well as memory. Note: Multiple references
** won't be shown; life sucks.
*/
if ( outmode==OUTMODE_CRUTCHES && length==0 )
return( ErrorText( OK_FULLFILE, filename+1 ));
if (fh=Open(filename+1, MODE_OLDFILE)) {
Seek(fh, startpos, OFFSET_BEGINNING);
unless( length ) { // Zero length means read *all*
Seek(fh, 0, OFFSET_END);
length=Seek(fh, 0, OFFSET_BEGINNING);
}
unless( length )
return( ErrorText( ERROR_READFILE, filename+1 ) );
if (temp=AllocMem(length+1,0)) {
if (length==Read(fh, temp, length)) {
temp[length]=0;
startOutput( outmode );
sendOutput( outmode, temp, length );
}
FreeMem(temp,length+1);
}
else{
return( ErrorText( ERROR_NOMEMORY, (void *)length ) );
}
Close(fh);
}
else{
return( ErrorText( ERROR_READFILE, filename+1 ) );
}
/*
** Multiple references section. Yes, I hacked it in.
*/
sprintf(buf_string,"# %s\\%s\n", filename+1, refline); /* First line */
sendOutput( outmode, buf_string, strlen( buf_string ) );
refline2 = refline;
filename2 = filename;
while( refline2 )
{
X(printf("Testing for more %s entries (%s)\n",searchword,refline2));
refline2+=strlen( refline2 )+1;
refline2 =searchMe(refline2,searchword,&temp);
if( temp )
filename2 = temp; // If new filename, update
if( refline2 )
{
X(printf("Got it: File %s refline=%lx/%s\n",
filename2,refline2,refline2));
strcpy (buf_string, "# ");
strncat(buf_string, filename2+1, STRING_MAX);
strncat(buf_string, "\\", STRING_MAX);
strncat(buf_string, refline2, STRING_MAX);
strncat(buf_string, "\n", STRING_MAX); // !!! ANSI Misfeature
sendOutput( outmode, buf_string, strlen( buf_string ) );
}
}
return( endOutput( outmode ) );
}
/*
** Reverse case insensitive string compare specialized for paths
** Compare:
** Help Request = foo.doc/AllocMem
** Full path = work:doc/foo.doc
** If path part matches full path, return 0, else return 1.
*/
int strpathcmp( path, candidate)
const char *path;
const char *candidate;
{
const char *pathe;
const char *cande;
typedef unsigned char ubyte;
cande = tailpath_p( candidate );
if( cande == candidate )
return( 0 ); // Trivial case: No path to compare
cande--; // foo.doc/AllocMem
pathe = path+strlen(path); // ^
while( (cande > candidate) && (pathe > path) ) {
pathe--;
cande--;
if (tolower(*(ubyte *)pathe) != tolower(*(ubyte *)cande))
return( 1 );
}
return( 0 );
}
/*
** Return just filename part of complete or incomplete path
*/
char *tailpath_p( char *pathname )
{
char * temp;
if( temp=strrchr( pathname, '\\' ) )
return( ++temp );
else if( temp=strrchr( pathname, ':' ) )
return( ++temp );
else
return( pathname );
}
char *ErrorText( int error, void * auxdata )
{
char * localstring;
switch( error ) {
case OK_TEMPFILE:
localstring = "T %s";
break;
case OK_FULLFILE:
localstring = "F %s";
break;
case ERROR_NOTOOLTYPE:
localstring = "E No \"VIEWER\" tooltype in icon!";
break;
case ERROR_NOTFOUND:
localstring = "E Item \"%s\" not found";
break;
case ERROR_BADFORMAT:
localstring = "E Corrupt line in s:DICEHelp.index";
break;
case ERROR_BADCOMMAND: // Handled as a rexx error number
case ERROR_READFILE:
localstring = "E Error reading \"%s\"";
break;
case ERROR_NOMEMORY: // Out of memory error !!!
localstring = "E Out of memory - %d bytes needed";
break;
case ERROR_WRITEFILE: // Error writing temporary file to T: !!!
localstring = "E Error writing \"%s\"";
break;
default:
localstring = "E Internal error!";
}
sprintf( buf_string, localstring, auxdata ); // !!! Length limit
return( buf_string );
}